import { Component, EventEmitter, HostBinding, Input, OnInit, Output, TemplateRef, ViewChild } from '@angular/core';
import { IdService } from '@farris/ui-common';
import { NotifyService } from '@farris/ui-notify';
import { TreeNode, TreeTableComponent } from '@farris/ui-treetable';
import { DomService, SchemaService, DesignViewModelService, FormViewModel, FormBasicService } from '@farris/designer-services';
import { DgControl } from '../../../../../../utils/dg-control';
import { ControlService } from '../../../../../../service/control.service';
import { FieldTreeBuilder } from '@farris/designer-devkit';
import { ControlEventPropertyIDList } from '../../../../../../utils/control-event-prop';
import { FieldTreeNode } from '@farris/designer-devkit';

@Component({
  selector: 'app-split-form-component',
  templateUrl: './split-form-component.component.html',
  styleUrls: ['./split-form-component.component.css']
})
export class SplitFormComponent implements OnInit {
  /**  控件和schema的映射类，由设计器提供 */
  @Input() schemaDOMMapping: any;

  /** 组件id */
  @Input() componentId: string;

  /** 组件ref节点的父容器id */
  @Input() componentParentContainerId: string;

  @Output() closeModal = new EventEmitter<any>();
  @Output() submitModal = new EventEmitter<any>();


  @ViewChild('footer') modalFooter: TemplateRef<any>;
  @ViewChild('bindFieldColTpl') bindFieldColTpl: TemplateRef<any>;

  @HostBinding('class')
  class = 'd-flex h-100 py-2 px-3';

  /** 卡片组件节点 */
  componentNode: any;

  /** 卡片组件内的Form节点 */
  compFormNode: any;

  /** 树表数据 */
  treeData: TreeNode[] = [];

  /** 树表列配置 */
  treeCols = [];

  /** 树表实例 */
  @ViewChild('treeTable') treeTable: TreeTableComponent;

  movedViewModelFieldIds = [];

  movedControls = [];

  componentTitle: string;


  constructor(
    private domService: DomService,
    private notifyService: NotifyService,
    private schemaService: SchemaService,
    private formBasicService: FormBasicService,
    private controlService: ControlService,
    private dgVMService: DesignViewModelService,
    private idService: IdService) { }

  ngOnInit() {
    this.componentNode = this.domService.getComponentById(this.componentId);

    this.treeData = this.buildFieldTree();

    this.compFormNode = this.domService.selectNode(this.componentNode, item => item.type === DgControl.Form.type);
    this.movedControls = [];
    this.movedViewModelFieldIds = [];

    this.treeCols = [
      { field: 'name', title: '名称' },
      { field: 'bindingPath', title: '绑定字段', template: this.bindFieldColTpl }];

    const { name: tableName } = this.schemaService.getTableInfoByViewModelId(this.componentNode.viewModel);
    this.componentTitle = tableName;

  }
  /**
   * 构件字段树表
   * @returns 树表数据
   */
  private buildFieldTree(): TreeNode[] {
    const fieldTreeBuilder = new FieldTreeBuilder(this.schemaDOMMapping, this.dgVMService, this.domService, this.formBasicService);

    return fieldTreeBuilder.buildFieldTreeData(this.componentNode.viewModel);
  }

  clickCancel() {
    this.closeModal.emit();
  }

  clickConfirm() {

    if (!this.componentTitle) {
      this.notifyService.warning('请填写组件标题');
      return;
    }
    if (!this.getSelectedControls()) {
      return;
    }


    // 1、创建新组件和VM
    const newViewModel = this.addNewFormComponent();

    // 2、移除旧组件下的控件
    this.removeControlsInComponent();

    // 3、移除旧组件VM的记录
    const viewModel = this.domService.getViewModelById(this.componentNode.viewModel);
    if (viewModel && viewModel.fields) {
      viewModel.fields = viewModel.fields.filter(f => !this.movedViewModelFieldIds.includes(f.id));
    }

    // 4、移动控件绑定的命令
    this.moveViewModelCommands(newViewModel);

    this.submitModal.emit();
  }

  /**
   * 字段搜索
   */
  searchField($event) {
    if ($event) {
      const { field, value } = $event;
      this.treeTable.searchHandle.search(field, value);
    } else {
      this.treeTable.searchHandle.search('*', '');
    }

  }



  private getSelectedControls() {
    const checkeds = this.treeTable.checkeds as FieldTreeNode[];
    if (!checkeds || checkeds.length === 0) {
      this.notifyService.warning('请选择字段');
      return false;
    }
    checkeds.forEach(checkedNode => {
      if (checkedNode.isGroupNode) {
        return;
      }
      if (!checkedNode.isNoBinding) {
        this.movedViewModelFieldIds.push(checkedNode.data.id);
      }
      this.movedControls.push(checkedNode.control);
    });

    return true;
  }

  /**
   * 创建新的卡片组件
   */
  private addNewFormComponent() {
    const viewModel = this.domService.getViewModelById(this.componentNode.viewModel);
    const { code: tableCode, name: tableName } = this.schemaService.getTableInfoByViewModelId(this.componentNode.viewModel);

    const cmpGUID = tableCode + '-' + Math.random().toString(36).slice(2, 6);


    // 1、创建组件引用节点
    const compRefMetadata = this.controlService.getControlMetaData(DgControl.ComponentRef.type);
    Object.assign(compRefMetadata, {
      id: cmpGUID + '-component-ref',
      component: cmpGUID + '-component'
    });


    // 2、 创建component节点
    const cmpMetadata = this.controlService.getControlMetaData(DgControl.Component.type);
    const contents = this.assembleFormCmpContents(cmpGUID, tableName);
    Object.assign(cmpMetadata, {
      id: cmpGUID + '-component',
      viewModel: cmpGUID + '-viewmodel',
      componentType: this.componentNode.componentType,
      appearance: this.componentNode.appearance,
      contents
    });

    // 3、 创建viewModel节点
    const innerVMFields = [];
    this.movedViewModelFieldIds.forEach(fieldId => {
      const vmField = viewModel.fields.find(f => f.id === fieldId);
      innerVMFields.push(Object.assign({}, vmField, { groupId: null, groupName: null }));

    });

    const vmMetadata = new FormViewModel();
    Object.assign(vmMetadata, {
      id: cmpGUID + '-viewmodel',
      code: cmpGUID + '-viewmodel',
      name: this.componentTitle,
      bindTo: viewModel.bindTo,
      parent: viewModel.parent,
      fields: innerVMFields,
      commands: [],
      states: viewModel.states, // 变量全部拷贝（因为控件的各种属性也可能绑定变量，这里不再依次判断）
      enableValidation: viewModel.enableValidation,
      pagination: {
        enable: false
      }
    });

    this.insertComponent(cmpMetadata, compRefMetadata, vmMetadata);

    return vmMetadata;
  }
  /**
   * 将组件相关节点插入DOM
   * @param componentBindingSourceContext 组件构造信息
   * @param componentRefParentNode 组件引用节点的父节点
   */
  private insertComponent(cmpMetadata: any, compRefMetadata: any, vmMetadata: any) {

    // 在当前组件下方插入ComponentRef
    const componentParentContainerNode = this.domService.domDgMap.get(this.componentParentContainerId);
    if (!componentParentContainerNode) {
      return;
    }
    const currentElementIndex = componentParentContainerNode.contents.findIndex(el => el.component === this.componentId);
    if (currentElementIndex > -1) {
      componentParentContainerNode.contents.splice(currentElementIndex + 1, 0, compRefMetadata);

      this.domService.addComponent(cmpMetadata);
      this.domService.addViewModel(vmMetadata);
    }
  }
  /**
   * 组装卡片组件内容
   */
  private assembleFormCmpContents(cmpGUID: string, tableName: string) {

    // 1、创建section
    let oldSection;
    if (this.componentNode.contents && this.componentNode.contents.length > 0) {
      oldSection = this.componentNode.contents.find(c => c.type === DgControl.Section.type);
    }
    if (!oldSection) {
      oldSection = this.controlService.getControlMetaData(DgControl.Section.type);
    }
    const section = Object.assign({}, oldSection, {
      id: cmpGUID + '-form-section',
      contents: [],
      showHeader: true,
      mainTitle: this.componentTitle,
      draggable: false,
      enableMaximize: false,
      enableAccordion: true,
      toolbar: {
        type: 'SectionToolbar',
        position: 'inHead',
        contents: []
      }
    });

    // 2、创建form
    const layoutForm = this.controlService.getControlMetaData(DgControl.Form.type);
    Object.assign(layoutForm, {
      id: cmpGUID + '-form-layout',
      appearance: this.compFormNode.appearance,
      contents: this.movedControls,
      controlsInline: this.compFormNode.controlsInline,
      draggable: false
    });
    section.contents = [layoutForm];

    return [section];

  }

  /**
   * 移除当前组件中的控件
   */
  private removeControlsInComponent() {
    const removedControlIds = this.movedControls.map(control => control.id);

    this.compFormNode.contents.forEach(contentElement => {
      if (contentElement.type === DgControl.FieldSet.type) {
        contentElement.contents = contentElement.contents.filter(co => !removedControlIds.includes(co.id));
      }
    });

    this.compFormNode.contents = this.compFormNode.contents.filter(co => {
      if (removedControlIds.includes(co.id)) {
        return false;
      }
      if (co.type === DgControl.FieldSet.type && co.contents && co.contents.length === 0) {
        return false;
      }
      return true;
    });
  }
  /**
   * 拷贝控件涉及的命令
   * @param newViewModel 新视图模型对象
   */
  private moveViewModelCommands(newViewModel: any) {
    const eventCodeList = Object.keys(ControlEventPropertyIDList);
    const currentViewModel = this.domService.getViewModelById(this.componentNode.viewModel);

    // 多个控件绑定一个命令时，不重复创建新命令
    const commandMap = {};
    this.movedControls.forEach(control => {
      Object.keys(control).forEach(propId => {
        const e = eventCodeList.find(key => key === propId);
        if (e && control[e]) {
          const oldCommand = currentViewModel.commands.find(c => c.code === control[e]);
          if (oldCommand) {
            // 新建命令
            let newCommand = commandMap[oldCommand.code];
            if (!newCommand) {
              newCommand = this.createNewCommand(oldCommand);
              commandMap[oldCommand.code] = newCommand;

              newViewModel.commands.push(newCommand);
            }


            // 修改控件绑定的命令
            control[e] = newCommand.code;

          }

        }
      });
    });

    // 字段值变化前、后事件
    const fieldEvents = ['valueChanging', 'valueChanged'];
    newViewModel.fields.forEach(field => {
      fieldEvents.forEach(event => {
        if (field[event]) {
          const oldCommand = currentViewModel.commands.find(c => c.code === field[event]);
          if (commandMap[oldCommand.code]) {
            field[event] = commandMap[oldCommand.code].code;
          } else {

            const newCommand = this.createNewCommand(oldCommand);
            commandMap[oldCommand.code] = newCommand;
            newViewModel.commands.push(newCommand);

            field[event] = newCommand.code;
          }
        }
      });

    });

    // TODO 校验当前VM的命令有没有不用了的，不用的命令移除掉
  }



  private createNewCommand(oldCommand: any) {
    // 1、新建命令
    const guiId = this.idService.generate();
    const newCommand = Object.assign({}, oldCommand, {
      id: guiId,
      code: oldCommand.code + guiId.slice(0, 4),
      name: oldCommand.name + guiId.slice(0, 4)
    });


    // 2、新建的命令添加到webCmds节点下
    const webCmds = this.domService.getWebCmds();

    const cmp = webCmds.find(cmd => cmd.id === oldCommand.cmpId);
    if (cmp) {
      cmp.refedHandlers.push({
        host: guiId,
        handler: oldCommand.handlerName
      });
    }

    return newCommand;
  }
}
